﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security;
using System.Runtime.InteropServices;
using System.Windows.Media;
using System.Windows;

namespace GrapeCity.Win32
{
    static class UnsafeNativeMethods
    {
        private static readonly Version VistaOSVersion = new Version(6, 0);
        public delegate int BrowseCallbackProc(IntPtr hwnd, int msg, IntPtr lParam, IntPtr lpData);

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        public class BROWSEINFO
        {
            public IntPtr hwndOwner;
            public IntPtr pidlRoot;
            public IntPtr pszDisplayName;
            public string lpszTitle;
            public int ulFlags;
            public UnsafeNativeMethods.BrowseCallbackProc lpfn;
            public IntPtr lParam;
            public int iImage;
        }

        internal static bool IsVista
        {
            get
            {
                OperatingSystem oSVersion = Environment.OSVersion;
                if (oSVersion == null) return false;
                return (oSVersion.Platform == PlatformID.Win32NT
                    && oSVersion.Version.CompareTo(VistaOSVersion) >= 0);
            }
        }


        [DllImport("ole32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
        internal static extern void CoTaskMemFree(IntPtr pv);

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr SendMessage(HandleRef hWnd, int msg, int wParam, string lParam);

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr SendMessage(HandleRef hWnd, int msg, int wParam, int lParam);

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr SendMessage(HandleRef hWnd, int msg, int wParam, [In, Out] NativeMethods.LOGFONT lParam);


        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr SendDlgItemMessage(HandleRef hDlg, int nIDDlgItem, int Msg, IntPtr wParam, IntPtr lParam);
 

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr GetDC(HandleRef hWnd);

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern int ReleaseDC(HandleRef hWnd, HandleRef hDC);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr GetModuleHandle(string modName);

        [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
        public static extern IntPtr GetDlgItem(HandleRef hWnd, int nIDDlgItem);


        [SuppressUnmanagedCodeSecurity]
        internal class Shell32
        {
            [DllImport("shell32.dll", CharSet = CharSet.Auto)]
            public static extern IntPtr SHBrowseForFolder([In] UnsafeNativeMethods.BROWSEINFO lpbi);

            public static int SHGetFolderPathEx(ref Guid rfid,
                uint dwFlags,
                IntPtr hToken,
                [MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszPath,
                uint cchPath)
            {
                if (!UnsafeNativeMethods.IsVista) throw new NotSupportedException();
                return SHGetFolderPathExPrivate(ref rfid, dwFlags, hToken, pszPath, cchPath);
            }

            [DllImport("shell32.dll", EntryPoint = "SHGetFolderPathEx")]
            private static extern int SHGetFolderPathExPrivate(ref Guid rfid,
                uint dwFlags,
                IntPtr hToken,
                [MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszPath,
                uint cchPath);

            [DllImport("shell32.dll")]
            public static extern int SHGetMalloc([Out, MarshalAs(UnmanagedType.LPArray)] UnsafeNativeMethods.IMalloc[] ppMalloc);

            [DllImport("shell32.dll", CharSet = CharSet.Auto)]
            public static extern bool SHGetPathFromIDList(IntPtr pidl,
                IntPtr pszPath);

            [DllImport("shell32.dll")]
            public static extern int SHGetSpecialFolderLocation(IntPtr hwnd,
                int csidl,
                ref IntPtr ppidl);

            [DllImport("shell32.dll")]
            public static extern int SHILCreateFromPath([MarshalAs(UnmanagedType.LPWStr)] string pszPath,
                out IntPtr ppIdl,
                ref uint rgflnOut);
        }

        [SuppressUnmanagedCodeSecurity]
        [ComImport, Guid("00000002-0000-0000-c000-000000000046")]
        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        public interface IMalloc
        {
            [PreserveSig]
            IntPtr Alloc(int cb);
            [PreserveSig]
            IntPtr Realloc(IntPtr pv, int cb);
            [PreserveSig]
            void Free(IntPtr pv);
            [PreserveSig]
            int GetSize(IntPtr pv);
            [PreserveSig]
            int DidAlloc(IntPtr pv);
            [PreserveSig]
            void HeapMinimize();
        }


    }

    static class SafeNativeMethods
    {
        [DllImport("comdlg32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern bool ChooseFont([In, Out] NativeMethods.CHOOSEFONT cf);

        [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
        public static extern bool ShowWindow(HandleRef hWnd, int nCmdShow);

    }

    static class NativeMethods
    {
        public static readonly int BFFM_SETSELECTION = Marshal.SystemDefaultCharSize == 1 ? 0x466 : 0x467;
        public static HandleRef NullHandleRef = new HandleRef(null, IntPtr.Zero);


        public delegate IntPtr WndProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto), CLSCompliant(false)]
        public class CHOOSEFONT
        {
            public int lStructSize = Marshal.SizeOf(typeof(NativeMethods.CHOOSEFONT));
            public IntPtr hwndOwner;
            public IntPtr hDC;
            public IntPtr lpLogFont;
            public int iPointSize;
            public int Flags;
            public int rgbColors;
            public IntPtr lCustData = IntPtr.Zero;
            public NativeMethods.WndProc lpfnHook;
            public string lpTemplateName;
            public IntPtr hInstance;
            public string lpszStyle;
            public short nFontType;
            public short ___MISSING_ALIGNMENT__;
            public int nSizeMin;
            public int nSizeMax;
        }

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        public class LOGFONT
        {
            public int lfHeight;
            public int lfWidth;
            public int lfEscapement;
            public int lfOrientation;
            public int lfWeight;
            public byte lfItalic;
            public byte lfUnderline;
            public byte lfStrikeOut;
            public byte lfCharSet;
            public byte lfOutPrecision;
            public byte lfClipPrecision;
            public byte lfQuality;
            public byte lfPitchAndFamily;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)]
            public string lfFaceName;
            public LOGFONT()
            {
            }

            public LOGFONT(NativeMethods.LOGFONT lf)
            {
                this.lfHeight = lf.lfHeight;
                this.lfWidth = lf.lfWidth;
                this.lfEscapement = lf.lfEscapement;
                this.lfOrientation = lf.lfOrientation;
                this.lfWeight = lf.lfWeight;
                this.lfItalic = lf.lfItalic;
                this.lfUnderline = lf.lfUnderline;
                this.lfStrikeOut = lf.lfStrikeOut;
                this.lfCharSet = lf.lfCharSet;
                this.lfOutPrecision = lf.lfOutPrecision;
                this.lfClipPrecision = lf.lfClipPrecision;
                this.lfQuality = lf.lfQuality;
                this.lfPitchAndFamily = lf.lfPitchAndFamily;
                this.lfFaceName = lf.lfFaceName;
            }
        }
    }

    static class ColorHelper
    {
        public static int ToWin32(this Color color)
        {
            return 0;
        }

        public static bool IsEmpty(this Color color)
        {
            return color.A == 0 && color.R == 0 && color.G == 0 && color.B == 0;
        }

        public static Color ToOleColor(this int oleColor)
        {
            unchecked
            {
                if ((oleColor & ((int)0xff000000L)) == (int)0x80000000
                    && (oleColor & 0xffffff) <= 0x1e)
                {
                    switch (oleColor)
                    {
                        case (int)0x80000000: return SystemColors.ScrollBarColor;
                        case (int)0x80000001: return SystemColors.DesktopColor;
                        case (int)0x80000002: return SystemColors.ActiveCaptionColor;
                        case (int)0x80000003: return SystemColors.InactiveCaptionColor;
                        case (int)0x80000004: return SystemColors.MenuColor;
                        case (int)0x80000005: return SystemColors.WindowColor;
                        case (int)0x80000006: return SystemColors.WindowFrameColor;
                        case (int)0x80000007: return SystemColors.MenuTextColor;
                        case (int)0x80000008: return SystemColors.WindowTextColor;
                        case (int)0x80000009: return SystemColors.ActiveCaptionTextColor;
                        case (int)0x8000000a: return SystemColors.ActiveBorderColor;
                        case (int)0x8000000b: return SystemColors.InactiveBorderColor;
                        case (int)0x8000000c: return SystemColors.AppWorkspaceColor;
                        case (int)0x8000000d: return SystemColors.HighlightColor;
                        case (int)0x8000000e: return SystemColors.HighlightTextColor;
                        case (int)0x8000000f: return SystemColors.ControlColor;
                        case (int)0x80000010: return SystemColors.ControlDarkColor;
                        case (int)0x80000011: return SystemColors.GrayTextColor;
                        case (int)0x80000012: return SystemColors.ControlTextColor;
                        case (int)0x80000013: return SystemColors.InactiveCaptionTextColor;
                        case (int)0x80000014: return SystemColors.ControlLightLightColor;
                        case (int)0x80000015: return SystemColors.ControlDarkDarkColor;
                        case (int)0x80000016: return SystemColors.ControlLightColor;
                        case (int)0x80000017: return SystemColors.InfoTextColor;
                        case (int)0x80000018: return SystemColors.InfoColor;
                        case (int)0x8000001a: return SystemColors.HotTrackColor;
                        case (int)0x8000001b: return SystemColors.GradientActiveCaptionColor;
                        case (int)0x8000001c: return SystemColors.GradientInactiveCaptionColor;
                        case (int)0x8000001d: return SystemColors.MenuHighlightColor;
                        case (int)0x8000001e: return SystemColors.MenuBarColor;
                    }
                }
                return Color.FromArgb(0xFF,
                    (byte)(oleColor & 0xff), 
                    (byte)(oleColor >> 0x8 & 0xff), 
                    (byte)(oleColor >> 0x10 & 0xff));
            }
        }
    }
}
